﻿using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel;
using DeklaritModel;
using MVCApplication.Helpers;

namespace MVCApplication.Controllers
{
    public class InvoiceController : CommonController
    {
		#region Properties
		
		protected DeklaritModel.InvoiceDataSet  dsInvoiceDataSet1;
		
		[Browsable(false)]
        public virtual IInvoiceDataAdapter DataAdapter 
        {
            get 
            {
                return DataAdapterFactory.GetInvoiceDataAdapter(); 
            }
        }
		
		#endregion
		
		#region WorkWith Action
		
        public ActionResult WorkWith(bool? prompt, string returnItems, string fillByMethod, string filterValues)
        {
            dsInvoiceDataSet1 = new InvoiceDataSet();
            int totalRecords, currentPage;
            FillDataSet(fillByMethod, filterValues, (int?)Session["m_WorkWithInvoiceCurrentPage"], out totalRecords, out currentPage);
            UpdateWorkWithPagerViewData(totalRecords, currentPage);
            ViewData["Prompt"] = prompt;
            ViewData["ReturnItems"] = returnItems != null ? returnItems.Split(',') : null;
            if (!(prompt ?? false))
            {
				SaveState();
            }
            return View(dsInvoiceDataSet1);
        }

        private void FillDataSet(string FillByMethod, string FilterValues, int? defaultCurrentPage, out int totalRecords, out int currentPage)
        {
            totalRecords = -1;
            currentPage = -1;

            if (!string.IsNullOrEmpty(FillByMethod))
            {
				
                switch (FillByMethod)
                {
					case "FillByClienteId" :
                        string[] splitted = GeneralFunctions.GetSplittedText(FilterValues);
                        if (splitted != null && FilterValues.Length >= 1)
                        {
                            totalRecords = DataAdapter.GetRecordCountByClienteId(System.Int16.Parse(splitted[0]));
                            currentPage = GetCurrentPage(totalRecords, defaultCurrentPage ?? 1);
                            DataAdapter.FillPageByClienteId(dsInvoiceDataSet1, System.Int16.Parse(splitted[0]), (currentPage - 1) * GridPageSize, GridPageSize);
                        }
						break;
                    default:
                        break;
                }
            }
            if (currentPage == -1)
            {
                totalRecords = DataAdapter.GetRecordCount();
                currentPage = GetCurrentPage(totalRecords, defaultCurrentPage ?? 1);
                DataAdapter.FillPage(dsInvoiceDataSet1, (currentPage - 1) * GridPageSize, GridPageSize);
            }
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult WorkWith(bool? prompt, string returnItems, int currentPage, int totalRecords, bool? expandRecords, int? rowIndex, string fillByMethod, string filterValues)
        {
			if(expandRecords.HasValue && expandRecords.Value)
			{
				GetDataSet();
                InvoiceDataSet expandedDS = new InvoiceDataSet();
                DataAdapter.Fill(expandedDS, dsInvoiceDataSet1.Invoice[rowIndex.Value].InvoiceId);
                ViewData["InvoiceExpandedModel"] = expandedDS;
                ViewData["ExpandedRowIndex"] = rowIndex;
                ViewData["ExpandRecords"] = true;				
			}
			else
			{
				Session["m_WorkWithInvoiceCurrentPage"] = currentPage;
				dsInvoiceDataSet1 = new InvoiceDataSet();
                FillDataSet(fillByMethod, filterValues, currentPage, out totalRecords, out currentPage);
            }
            UpdateWorkWithPagerViewData(totalRecords, currentPage);
            ViewData["Prompt"] = prompt;
            ViewData["ReturnItems"] = returnItems != null ? returnItems.Split(',') : null;
            if(!(prompt ?? false))
            {
				SaveState();
            }
			return this.PartialView("WorkWithControl", dsInvoiceDataSet1);
        } 
        
        #endregion

		#region Create Action

        public ActionResult Create(bool? prompt, string promptReturnFunction, string promptAttribute, string instantiatedAttributes)
        {
			dsInvoiceDataSet1 = new InvoiceDataSet();
			GeneralFunctions.ChangeTablesDefaults(dsInvoiceDataSet1.Invoice);
			InvoiceDataSet.InvoiceRow row = dsInvoiceDataSet1.Invoice.NewInvoiceRow();
            InstantiateAttributes(row, instantiatedAttributes);
			dsInvoiceDataSet1.Invoice.AddInvoiceRow(row);
			SaveState();
            ViewData["Mode"] = EnumMode.Insert;
            ViewData["Prompt"] = prompt;
            ViewData["PromptReturnFunction"] = promptReturnFunction;
            ViewData["PromptAttribute"] = promptAttribute;
			return View("Edit", dsInvoiceDataSet1);
        }
        
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(bool? prompt, string promptReturnFunction, string promptAttribute, string instantiatedAttributes, string InvoiceDescription, Int16? ClienteId, Int16? InvoiceLineLastIndex, MenuAction menuAction)
        {
			GetDataSet();
            // Validation logic
            ValidateInvoice(InvoiceDescription, ClienteId, InvoiceLineLastIndex, EnumMode.Insert, true);
            if (!ModelState.IsValid)
            {
                ViewData["Mode"] = EnumMode.Insert;
				SetReadOnlyToInstantiateAttributes(instantiatedAttributes);
                if (prompt ?? false)
                {
					ViewData["Prompt"] = prompt;
					ViewData["PromptAttribute"] = promptAttribute;
					return this.PartialView("EditControl", dsInvoiceDataSet1);
                }
                else
                {
					return View("Edit", dsInvoiceDataSet1);
                }
            }

            // Database logic
            try
            {                
                InvoiceDataSet.InvoiceRow row = dsInvoiceDataSet1.Invoice.Rows[0] as InvoiceDataSet.InvoiceRow;
				row.InvoiceDescription = InvoiceDescription;
				if (ClienteId.HasValue)
					row.ClienteId = ClienteId.Value;
				else
					row.ClienteId = 0;
				if (InvoiceLineLastIndex.HasValue)
					row.InvoiceLineLastIndex = InvoiceLineLastIndex.Value;
				else
					row.InvoiceLineLastIndex = 0;
                DataAdapter.Update(dsInvoiceDataSet1);
                switch (menuAction)
                {
                    case MenuAction.Submit:
                        string dummy = UrlHistory.Pop(Session);
                        return RedirectToAction("Edit", new { InvoiceId = row.InvoiceId });
                    case MenuAction.SubmitAndNew:
                        return RedirectToAction("Create");
                    case MenuAction.SubmitAndReturn:
                        if (prompt ?? false)
                        {
                            ViewData["Prompt"] = true;
                            ViewData["PromptAttribute"] = promptAttribute;
                            ViewData["PromptReturn"] = true;
                            ViewData["Mode"] = EnumMode.Insert;
                            return this.PartialView("EditControl", dsInvoiceDataSet1);
                        }
                        else
                        {
                            return RedirectToAction("Return");
                        }
                    default:
                        throw new System.Exception("Invalid MenuAction: " + menuAction.ToString());
                }
            }
            catch(System.Exception exc)
            {
                ModelState.AddModelError("generalError", exc.Message);
				SetReadOnlyToInstantiateAttributes(instantiatedAttributes);
                ViewData["Mode"] = EnumMode.Insert;
                if (prompt ?? false)
                {
					ViewData["Prompt"] = prompt;
					ViewData["PromptAttribute"] = promptAttribute;
					return this.PartialView("EditControl", dsInvoiceDataSet1);
                }
                else
                {
					return this.PartialView("Edit", dsInvoiceDataSet1);
                }
            }
        }
		
		#endregion
		
		#region Edit Action

        public ActionResult Edit(Int16 InvoiceId)
        {
            ViewData["Mode"] = EnumMode.Update;
            try
            {
				dsInvoiceDataSet1 = new InvoiceDataSet();
				DataAdapter.Fill(dsInvoiceDataSet1, InvoiceId);
				SaveState();
				return this.PartialView("Edit", dsInvoiceDataSet1);
            }
            catch (System.Exception exc)
            {
                ModelState.AddModelError("generalError", exc.Message);
                return this.PartialView("Edit");
            }
        }
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(string InvoiceDescription, Int16? ClienteId, Int16? InvoiceLineLastIndex, MenuAction menuAction)
        {
			GetDataSet();
            ValidateInvoice(InvoiceDescription, ClienteId, InvoiceLineLastIndex, EnumMode.Update, false);
            if (!ModelState.IsValid)
            {
				ViewData["Mode"] = EnumMode.Update;
                switch (menuAction)
                {
                    case MenuAction.Submit:
                        return this.PartialView("EditControl", dsInvoiceDataSet1);
                    case MenuAction.SubmitAndReturn:
						return View("Edit", dsInvoiceDataSet1);
                    default:
                        throw new System.Exception("Invalid MenuAction: " + menuAction.ToString());
                }
            }

            try
            {				
                InvoiceDataSet.InvoiceRow row = dsInvoiceDataSet1.Invoice[0];
				row.InvoiceDescription = InvoiceDescription;
				if(ClienteId.HasValue)
				{
					row.ClienteId = ClienteId.Value;
				}
				else
				{					
					row.ClienteId = 0;
				}
				if(InvoiceLineLastIndex.HasValue)
				{
					row.InvoiceLineLastIndex = InvoiceLineLastIndex.Value;
				}
				else
				{					
					row.InvoiceLineLastIndex = 0;
				}
                DataAdapter.Update(dsInvoiceDataSet1);
                switch (menuAction)
                {
                    case MenuAction.Submit:
						ViewData["Mode"] = EnumMode.Update;
                        ModelState.AddModelError("generalMsg", "Data succesfully saved.");
                        return this.PartialView("EditControl", dsInvoiceDataSet1);
                    case MenuAction.SubmitAndReturn:
                        return RedirectToAction("Return");
                    default:
                        throw new System.Exception("Invalid MenuAction: " + menuAction.ToString());
                }
            }
            catch(System.Exception exc)
            {
                ModelState.AddModelError("generalError", exc.Message);
				ViewData["Mode"] = EnumMode.Update;
                switch (menuAction)
                {
                    case MenuAction.Submit:
                        return this.PartialView("EditControl", dsInvoiceDataSet1);
                    case MenuAction.SubmitAndReturn:
						return View("Edit", dsInvoiceDataSet1);
                    default:
                        throw new System.Exception("Invalid MenuAction: " + menuAction.ToString());
                }
            }
        }

		#endregion
		
		#region Display Action

        public ActionResult Display(Int16 InvoiceId)
        {
            ViewData["Mode"] = EnumMode.Display;
            try
            {
				dsInvoiceDataSet1 = new InvoiceDataSet();
				DataAdapter.Fill(dsInvoiceDataSet1, InvoiceId);
				SaveState();
				return this.PartialView("Edit", dsInvoiceDataSet1);
            }
            catch (System.Exception exc)
            {
                ModelState.AddModelError("generalError", exc.Message);
                return this.PartialView("Edit");
            }
        }		
		#endregion

		#region Add, Edit and Delete lines for level Line

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult InvoiceLine_AddLine(bool? prompt, string promptReturnFunction, string promptAttribute, string instantiatedAttributes, string InvoiceDescription, Int16? ClienteId, Int16? InvoiceLineLastIndex, EnumMode mode)
        {
            GetDataSet();
            ViewData["InvoiceLineEditableIndex"] = dsInvoiceDataSet1.InvoiceLine.Rows.Count;
            ViewData["InvoiceLineAddingLine"] = true;
            SetReadOnlyToInstantiateAttributes(instantiatedAttributes);
            ViewData["Mode"] = mode;
            ViewData["Prompt"] = prompt;
            ViewData["PromptReturnFunction"] = promptReturnFunction;
            ViewData["PromptAttribute"] = promptAttribute;
            GeneralFunctions.ChangeTablesDefaults(dsInvoiceDataSet1.InvoiceLine);
            return this.PartialView("EditControl", dsInvoiceDataSet1);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult InvoiceLine_EditLine(bool? prompt, string promptReturnFunction, string promptAttribute, string instantiatedAttributes, string InvoiceDescription, Int16? ClienteId, Int16? InvoiceLineLastIndex, int rowIndex, EnumMode mode)
        {
            GetDataSet();
            ViewData["InvoiceLineEditableIndex"] = rowIndex;
            SetReadOnlyToInstantiateAttributes(instantiatedAttributes);
            ViewData["Mode"] = mode;
            return this.PartialView("EditControl", dsInvoiceDataSet1);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult InvoiceLine_DeleteLine(bool? prompt, string promptReturnFunction, string promptAttribute, string instantiatedAttributes, string InvoiceDescription, Int16? ClienteId, Int16? InvoiceLineLastIndex, int rowIndex, EnumMode mode)
        {
            GetDataSet();
            dsInvoiceDataSet1.InvoiceLine.Rows[rowIndex].Delete();
            SaveState();
            SetReadOnlyToInstantiateAttributes(instantiatedAttributes);
            ViewData["Mode"] = mode;
            ViewData["Prompt"] = prompt;
            ViewData["PromptReturnFunction"] = promptReturnFunction;
            ViewData["PromptAttribute"] = promptAttribute;
            return this.PartialView("EditControl", dsInvoiceDataSet1);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult InvoiceLine_ConfirmLine(bool? prompt, string promptReturnFunction, string promptAttribute, string instantiatedAttributes, string InvoiceDescription, Int16? ClienteId, Int16? InvoiceLineLastIndex, Int16? InvoiceLineId, Int16? ProductId, decimal? InvoiceLineProductValue, Int16? InvoiceLineProductQuantity, int rowIndex, EnumMode mode, bool? InvoiceLineAddingLine)
        {
            GetDataSet();
            try
            {
				DeklaritModel.InvoiceDataSet.InvoiceLineRow row;
				if(InvoiceLineAddingLine.HasValue && InvoiceLineAddingLine.Value)
				{
					GeneralFunctions.ChangeTablesDefaults(dsInvoiceDataSet1.InvoiceLine);
					row = dsInvoiceDataSet1.InvoiceLine.NewInvoiceLineRow();
					row.InvoiceId = ((InvoiceDataSet.InvoiceRow)dsInvoiceDataSet1.Invoice.Rows[0]).InvoiceId;
				}
				else
				{
					row = dsInvoiceDataSet1.InvoiceLine.Rows[rowIndex] as DeklaritModel.InvoiceDataSet.InvoiceLineRow;
				}
				if(InvoiceLineId.HasValue)
				{
					row.InvoiceLineId = InvoiceLineId.Value;
				}
				else
				{					
					row.InvoiceLineId = 0;
				}
				if(ProductId.HasValue)
				{
					row.ProductId = ProductId.Value;
				}
				else
				{					
					row.ProductId = 0;
				}
				if(InvoiceLineProductValue.HasValue)
				{
					row.InvoiceLineProductValue = InvoiceLineProductValue.Value;
				}
				else
				{					
					row.InvoiceLineProductValue = 0;
				}
				if(InvoiceLineProductQuantity.HasValue)
				{
					row.InvoiceLineProductQuantity = InvoiceLineProductQuantity.Value;
				}
				else
				{					
					row.InvoiceLineProductQuantity = 0;
				}
				if(InvoiceLineAddingLine.HasValue && InvoiceLineAddingLine.Value)
				{
					dsInvoiceDataSet1.InvoiceLine.Rows.Add(row);
				}
				SaveState();
            }
            catch (System.Exception exc)
            {
                ModelState.AddModelError("generalError", exc.Message);
                ViewData["InvoiceLineEditableIndex"] = rowIndex;
                ViewData["InvoiceLineAddingLine"] = InvoiceLineAddingLine;
            }
            SetReadOnlyToInstantiateAttributes(instantiatedAttributes);
            ViewData["Mode"] = mode;
            ViewData["Prompt"] = prompt;
            ViewData["PromptReturnFunction"] = promptReturnFunction;
            ViewData["PromptAttribute"] = promptAttribute;
            return this.PartialView("EditControl", dsInvoiceDataSet1);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult InvoiceLine_CancelLine(bool? prompt, string promptReturnFunction, string promptAttribute, string instantiatedAttributes, string InvoiceDescription, Int16? ClienteId, Int16? InvoiceLineLastIndex, int rowIndex, EnumMode mode)
        {
            GetDataSet();
            SetReadOnlyToInstantiateAttributes(instantiatedAttributes);
            ViewData["Mode"] = mode;
            ViewData["Prompt"] = prompt;
            ViewData["PromptReturnFunction"] = promptReturnFunction;
            ViewData["PromptAttribute"] = promptAttribute;
            return this.PartialView("EditControl", dsInvoiceDataSet1);
        }

		#endregion
		
		#region Delete Action

		[AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Delete(Int16 InvoiceId)
        {
            ViewData["Mode"] = EnumMode.Delete;
            try
            {
				dsInvoiceDataSet1 = new InvoiceDataSet();
				DataAdapter.Fill(dsInvoiceDataSet1, InvoiceId);
				SaveState();
				return this.PartialView("Edit", dsInvoiceDataSet1);
            }
            catch (System.Exception exc)
            {
                ModelState.AddModelError("generalError", exc.Message);
                return this.PartialView("Edit");
            }
        }
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Delete()
        {
			GetDataSet();
            try
            {
                InvoiceDataSet.InvoiceRow row = dsInvoiceDataSet1.Invoice[0];
                row.Delete();
                DataAdapter.Update(dsInvoiceDataSet1);
                return RedirectToAction("Return");
            }
            catch (System.Exception exc)
            {
                ModelState.AddModelError("generalError", exc.Message);
                dsInvoiceDataSet1.RejectChanges();
                ViewData["Mode"] = EnumMode.Delete;
                return this.PartialView("Edit", dsInvoiceDataSet1);
            }
        }
		
		#endregion
		
		#region NewRelated and DisplayRelated Actions

		#endregion
		
		#region Auxiliar Methods
        
        private void GetDataSet() 
        {
            //  Get DataSet from Page Session 
			dsInvoiceDataSet1 = ((InvoiceDataSet)(Session["DataSetInvoice"]));
		}
        
        private void SaveState() 
        {
            //  Save DataSet in Page Session 
			Session.Add("DataSetInvoice", dsInvoiceDataSet1 );
		}
		
        protected void ValidateInvoice(string InvoiceDescription, Int16? ClienteId, Int16? InvoiceLineLastIndex, EnumMode mode, bool validateKey)
        {
            /*if (contactToValidate.FirstName.Trim().Length == 0)
                ModelState.AddModelError("FirstName", "First name is required.");
            if (contactToValidate.LastName.Trim().Length == 0)
                ModelState.AddModelError("LastName", "Last name is required.");
            if (contactToValidate.Phone.Length > 0 && !Regex.IsMatch(contactToValidate.Phone, @"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}"))
                ModelState.AddModelError("Phone", "Invalid phone number.");
            if (contactToValidate.Email.Length > 0 && !Regex.IsMatch(contactToValidate.Email, @"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"))
                ModelState.AddModelError("Email", "Invalid email address.");*/
        }

        protected void UpdateWorkWithPagerViewData(int totalRecords, int currentPage)
        {
            ViewData["CurrentPage"] = currentPage;
            ViewData["TotalRecords"] = totalRecords;
            int totalPages = (int)System.Math.Ceiling((double)totalRecords / GridPageSize);
            if (totalPages <= 1)
            {
                ViewData["isFirstPage"] = true;
                ViewData["isLastPage"] = true;
            }
            else
            {
                ViewData["isFirstPage"] = (currentPage <= 1);
                ViewData["isLastPage"] = (currentPage >= totalPages);

                ViewData["lastPage"] = totalPages;
            }
            ViewData["PagerText"] = string.Format(Deklarit.Resources.Resources.pagerRows, totalRecords <= 0 ? 0 : (currentPage - 1) * GridPageSize + 1, Math.Min(currentPage * GridPageSize, totalRecords), totalRecords) + " - " + string.Format(Deklarit.Resources.Resources.pagerPage, currentPage, totalPages <= 0 ? 1 : totalPages);
        }
		
		#endregion
    }
}
